package cn.snmp.mutual.nms.util;

import cn.snmp.mutual.nms.*;
import cn.snmp.mutual.nms.mibs.MibOperations;
import cn.snmp.mutual.nms.mibs.MibProfileLoader;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import cn.snmp.mutual.uk.beans.UsmDiscoveryBean;
import cn.snmp.mutual.uk.pdu.*;
import cn.snmp.mutual.uk.stack.*;


@Slf4j
public class SnmpTarget {
    public static boolean isSessionCtrl;
    protected static int maxRecvSize;
    public static final int VERSION1 = 0;
    public static final int VERSION2C = 1;
    public static final int VERSION3 = 3;
    protected SnmpContextBasisFace context;
    public static int SHA1_PROTOCOL;
    public static int MD5_PROTOCOL;
    public static int AES_PROTOCOL;
    public static int DES_PROTOCOL;
    protected String m_strContextEngineId;
    protected int m_iAuthenticationProtocol;
    protected int m_iPrivacyProtocol;
    protected String m_strUserName;
    protected String m_strContextName;
    protected boolean m_bUseAuthentication;
    protected String m_strUserAuthenticationPassword;
    protected boolean m_bUsePrivacy;
    protected String m_strUserPrivacyPassword;
    private Object m_syncObject;
    protected String m_community;
    protected String m_writeCommunity;
    protected String m_targetHost;
    protected int m_targetPort;
    protected int m_retries;
    protected int m_MaxRepetitions;
    protected int m_NonRepeaters;
    protected int m_timeout;
    protected int m_snmpVersion;
    protected int m_maxRows;
    protected String[] m_oidList;
    protected int m_errCode;
    protected String m_errDesc;
    protected MibOperations m_operations;

    public SnmpTarget() {
        this.context = null;
        this.m_strContextEngineId = "";
        this.m_iAuthenticationProtocol = SnmpTarget.MD5_PROTOCOL;
        this.m_iPrivacyProtocol = SnmpTarget.DES_PROTOCOL;
        this.m_strUserName = "";
        this.m_strContextName = "";
        this.m_bUseAuthentication = false;
        this.m_strUserAuthenticationPassword = "";
        this.m_bUsePrivacy = false;
        this.m_strUserPrivacyPassword = "";
        this.m_syncObject = new Object();
        this.m_community = "public";
        this.m_writeCommunity = null;
        this.m_targetHost = "";
        this.m_targetPort = 161;
        this.m_retries = -1;
        this.m_MaxRepetitions = 50;
        this.m_NonRepeaters = 0;
        this.m_timeout = 5;
        this.m_snmpVersion = 1;
        this.m_maxRows = 1000;
        this.m_oidList = null;
        this.m_errCode = 0;
        this.m_errDesc = "";
        this.m_operations = null;
    }

    public void loadMibs(final String mibsProfile) {
        this.releaseResources();
        final MibProfileLoader loader = new MibProfileLoader(mibsProfile);
        this.m_operations = loader.load();
    }

    public MibOperations getMibOperations() {
        return this.m_operations;
    }

    public void releaseSnmpSession() {
        if (!SnmpTarget.isSessionCtrl) {
            this.context.destroy();
        }
    }

    private SnmpResult newSnmpResult() {
        return new SnmpResult();
    }

    public static void main(final String[] argvs) {
        try {
            AsnObject.debug = 7;
            final SnmpTarget target = new SnmpTarget();
            target.setTargetHost("10.1.5.206");
            target.setTargetPort(161);
            target.setSnmpVersion(1);
            target.setCommunity("public");
            target.setNonRepeaters(0);
            target.setMaxRepetitions(100);
            final String[] oids = {".1.3.6.1.2.1.17.7.1.4.2.1.2", ".1.3.6.1.2.1.17.7.1.4.2.1.3", ".1.3.6.1.2.1.17.7.1.4.2.1.4", ".1.3.6.1.2.1.17.7.1.4.2.1.5", ".1.3.6.1.2.1.17.7.1.4.2.1.6", ".1.3.6.1.2.1.17.7.1.4.2.1.7"};
            final SnmpResult r = target.newSnmpResult();
            final Varbind[] binds = target.performRequest("getbulk", oids, null, r);
            final SnmpVar[] snmpVars = new SnmpVar[binds.length];
            for (int i = 0; i < binds.length; ++i) {
                snmpVars[i] = ObjectConversion.changeVariable(binds[i].getValue());
                System.err.println(snmpVars[i].toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setObjectIDList(final String[] oids) {
        if (oids == null || oids.length == 0) {
            this.m_oidList = null;
            return;
        }
        this.m_oidList = new String[oids.length];
        for (int i = 0; i < this.m_oidList.length; ++i) {
            this.m_oidList[i] = oids[i];
        }
    }

    public SnmpOID[] getSnmpOIDList() {
        return ObjectConversion.string2oid(this.m_oidList);
    }

    public SnmpVar[] snmpGetList() {
        return this.snmpGetList(this.m_oidList);
    }

    public SnmpVar snmpGet(final SnmpOID snmpOID) {
        final SnmpOID[] list = {snmpOID};
        final SnmpVar[] svValues = this.snmpGetList(list);
        if (svValues == null) {
            return null;
        }
        return svValues[0];
    }

    public SnmpVar[] snmpGetList(final SnmpOID[] oids) {
        return this.snmpGetList(ObjectConversion.oid2string(oids));
    }

    public SnmpVar[] snmpGetList(final String[] oids) {
        if (oids == null || oids.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        try {
            final SnmpResult r = new SnmpResult();
            final Varbind[] binds = this.performRequest("get", oids, null, r);
            if (r.err_code != 0) {
                return null;
            }
            final SnmpVar[] snmpVars = new SnmpVar[binds.length];
            for (int i = 0; i < binds.length; ++i) {
                snmpVars[i] = ObjectConversion.changeVariable(binds[i].getValue());
            }
            return snmpVars;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public SnmpVarBind[] snmpGetVariableBindings() {
        if (this.m_oidList == null || this.m_oidList.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        try {
            final SnmpResult r = new SnmpResult();
            final Varbind[] binds = this.performRequest("get", this.m_oidList, null, r);
            if (r.err_code != 0) {
                return null;
            }
            final SnmpVar[] vars = new SnmpVar[binds.length];
            final SnmpVarBind[] snmpVarBinds = new SnmpVarBind[binds.length];
            for (int i = 0; i < binds.length; ++i) {
                final SnmpVar var = ObjectConversion.changeVariable(binds[i].getValue());
                final SnmpOID oid = (SnmpOID) ObjectConversion.changeVariable(binds[i].getOid());
                final SnmpVarBind bind = new SnmpVarBind(oid, var);
                snmpVarBinds[i] = bind;
            }
            return snmpVarBinds;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public SnmpVarBind[] snmpGetNextVariableBindings() {
        if (this.m_oidList == null || this.m_oidList.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        final SnmpVarBind[] binds = this.snmpGetNextVariableBindings(this.m_oidList);
        if (this.m_errCode == 0) {
            for (int i = 0; i < this.m_oidList.length; ++i) {
                this.m_oidList[i] = binds[i].getObjectID().toString();
            }
        }
        return binds;
    }

    public SnmpVarBind[] snmpGetNextVariableBindings(final SnmpOID[] oidList) {
        return this.snmpGetNextVariableBindings(ObjectConversion.oid2string(oidList));
    }

    public SnmpVarBind[] snmpGetNextVariableBindings(final String[] oidList, final boolean bUseGetBulk) {
        if (oidList == null || oidList.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        try {
            final SnmpResult r = new SnmpResult();
            Varbind[] binds = null;
            if (bUseGetBulk) {
                binds = this.performRequest("getbulk", oidList, null, r);
            } else {
                binds = this.performRequest("getnext", oidList, null, r);
            }
            if (r.err_code != 0) {
                return null;
            }
            final SnmpVar[] vars = new SnmpVar[binds.length];
            final SnmpVarBind[] snmpVarBinds = new SnmpVarBind[binds.length];
            for (int i = 0; i < binds.length; ++i) {
                final SnmpVar var = ObjectConversion.changeVariable(binds[i].getValue());
                final SnmpOID oid = (SnmpOID) ObjectConversion.changeVariable(binds[i].getOid());
                final SnmpVarBind bind = new SnmpVarBind(oid, var);
                snmpVarBinds[i] = bind;
            }
            return snmpVarBinds;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public SnmpVarBind[] snmpGetNextVariableBindings(final String[] oidList) {
        return this.snmpGetNextVariableBindings(oidList, false);
    }

    public SnmpVarBind[][] snmpGetAllVariableBindings() {
        return this.snmpGetAllVariableBindings(false);
    }

    public SnmpVarBind[][] snmpGetAllVariableBindings(final boolean bUseGetBulk) {
        if (this.m_oidList == null || this.m_oidList.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        try {
            final Vector<SnmpVarBind[]> v = new Vector<SnmpVarBind[]>();
            String strCurrentOid;
            final String strBaseOid = strCurrentOid = this.m_oidList[0].toString();
            final String[] oidlist = new String[this.m_oidList.length];
            for (int i = 0; i < this.m_oidList.length; ++i) {
                oidlist[i] = this.m_oidList[i];
            }
            for (int count = this.m_maxRows; count > 0; --count) {
                final SnmpVarBind[] binds = this.snmpGetNextVariableBindings(oidlist, bUseGetBulk);
                if (binds == null) {
                    break;
                }
                final String strNextOid = binds[0].getObjectID().toString();
                if (!strNextOid.startsWith(strBaseOid)) {
                    break;
                }
                if (strCurrentOid.equals(strNextOid)) {
                    log.debug("find circle lock at [" + strCurrentOid + "], break");
                    break;
                }
                for (int j = 0; j < oidlist.length; ++j) {
                    oidlist[j] = binds[j].getObjectID().toString();
                }
                strCurrentOid = strNextOid;
                v.add(binds);
            }
            final SnmpVarBind[][] bindsList = new SnmpVarBind[v.size()][this.m_oidList.length];
            for (int k = 0; k < v.size(); ++k) {
                bindsList[k] = v.get(k);
            }
            return bindsList;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public SnmpVar[] snmpSetVariables(final SnmpVar[] values) throws Exception {
        if (this.m_oidList == null || this.m_oidList.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        try {
            final SnmpResult r = new SnmpResult();
            final Varbind[] binds = this.performRequest("set", this.m_oidList, ObjectConversion.changeVariable(values), r);
            if (r.err_code != 0) {
                return null;
            }
            final SnmpVar[] vars = new SnmpVar[binds.length];
            for (int i = 0; i < binds.length; ++i) {
                vars[i] = ObjectConversion.changeVariable(binds[i].getValue());
            }
            return vars;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public SnmpVarBind[] snmpSetVariables(final SnmpVarBind[] binds) throws Exception {
        if (binds == null || binds.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        final String[] oids = new String[binds.length];
        final AsnObject[] vars = new AsnObject[binds.length];
        for (int i = 0; i < binds.length; ++i) {
            oids[i] = binds[i].getObjectID().toString();
            vars[i] = ObjectConversion.changeVariable(binds[i].getVariable());
        }
        try {
            final SnmpResult r = new SnmpResult();
            final Varbind[] returns = this.performRequest("set", oids, vars, r);
            if (r.err_code != 0) {
                return null;
            }
            final SnmpVarBind[] returnVarBinds = new SnmpVarBind[returns.length];
            for (int j = 0; j < binds.length; ++j) {
                final SnmpOID oid = (SnmpOID) ObjectConversion.changeVariable(returns[j].getOid());
                final SnmpVar var = ObjectConversion.changeVariable(returns[j].getValue());
                returnVarBinds[j] = new SnmpVarBind(oid, var);
            }
            return returnVarBinds;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public SnmpVarBind[] snmpSetVariablesWithReturnBinds(final SnmpVarBind[] binds) throws Exception {
        if (binds == null || binds.length < 1) {
            this.m_errCode = 21;
            this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            return null;
        }
        final String[] oids = new String[binds.length];
        final AsnObject[] vars = new AsnObject[binds.length];
        for (int i = 0; i < binds.length; ++i) {
            oids[i] = binds[i].getObjectID().toString();
            vars[i] = ObjectConversion.changeVariable(binds[i].getVariable());
        }
        try {
            final SnmpResult r = new SnmpResult();
            final Varbind[] returns = this.performRequestWithReturnBinds("set", oids, vars, r);
            if (returns == null) {
                return null;
            }
            final SnmpVarBind[] returnVarBinds = new SnmpVarBind[returns.length];
            for (int j = 0; j < binds.length; ++j) {
                final SnmpOID oid = (SnmpOID) ObjectConversion.changeVariable(returns[j].getOid());
                final SnmpVar var = ObjectConversion.changeVariable(returns[j].getValue());
                returnVarBinds[j] = new SnmpVarBind(oid, var);
            }
            return returnVarBinds;
        } catch (Exception e) {
            log.debug("" + e);
            return null;
        }
    }

    public int getErrorCode() {
        log.debug("" + ("------> getErrorCode() return [" + this.m_errCode + "]."));
        return this.m_errCode;
    }

    public String getErrorString() {
        log.debug(("------> getErrorString() return [" + this.m_errDesc + "]."));
        return this.m_errDesc;
    }

    public void releaseResources() {
        try {
            if (this.m_operations != null) {
                this.m_operations.unloadAllMibModules();
                this.m_operations = null;
            }
        } catch (Exception e) {
            this.m_operations = null;
            log.debug("" + e);
        }
    }

    public void setCommunity(final String community) {
        if (community == null) {
            return;
        }
        if (this.m_community.equals(community)) {
            return;
        }
        synchronized (this.m_syncObject) {
            this.m_community = community;
        }
    }

    public void setWriteCommunity(final String community) {
        if (community == null) {
            return;
        }
        if (this.m_writeCommunity != null && this.m_writeCommunity.equals(community)) {
            return;
        }
        this.m_writeCommunity = community;
    }

    public void setTargetHost(final String targetHost) {
        if (targetHost == null) {
            return;
        }
        if (targetHost.equals(this.m_targetHost)) {
            return;
        }
        this.m_targetHost = targetHost;
    }

    public void setTargetPort(final int targetPort) {
        if (this.m_targetPort != targetPort) {
            this.m_targetPort = targetPort;
        }
    }

    public void setRetries(final int retries) {
        if (retries < 0) {
            return;
        }
        this.m_retries = retries;
    }

    public void setTimeout(final int timeout) {
        if (timeout <= 0) {
            return;
        }
        this.m_timeout = timeout;
    }

    public void setSnmpVersion(final int snmpVersion) {
        if (this.m_snmpVersion != snmpVersion) {
            this.m_snmpVersion = snmpVersion;
        }
    }

    public void setMaxNumRows(final int maxRows) {
        this.m_maxRows = maxRows;
    }

    public void setMaxRepetitions(final int maxRepetitions) {
        this.m_MaxRepetitions = maxRepetitions;
    }

    public void setNonRepeaters(final int nonRepeaters) {
        this.m_NonRepeaters = nonRepeaters;
    }

    public void setParams(final String host, final String port, final String community, final String mib, final String[] oids) {
        if (oids == null || oids.equals("")) {
            return;
        }
        this.setTargetHost(host);
        this.setTargetPort(Integer.parseInt(port));
        this.setCommunity(community);
        this.m_oidList = oids;
    }

    public void setParams(final String host, final String port, final String community, final String mib, final String oid) {
        try {
            final String[] oids = {oid};
            this.setParams(host, port, community, mib, oids);
        } catch (Exception e) {
            log.debug("" + e);
        }
    }

    protected void initContext() {
        try {
            this.context = SnmpContextPool.getInstance().getSnmpContext(this.m_snmpVersion, this.m_targetHost, this.m_targetPort);
            if (this.context != null && 3 == this.m_snmpVersion) {
                this.setUsm((SnmpContextv3Face) this.context);
            }
        } catch (Exception e) {
            log.debug("" + e);
        }
    }

    protected void setAuthenticationProtocol(final int iAuthenticationProtocol) {
        if (this.m_iAuthenticationProtocol == iAuthenticationProtocol) {
            return;
        }
        this.m_iAuthenticationProtocol = iAuthenticationProtocol;
    }

    protected void setPrivacyProtocol(final int iPrivacyProtocol) {
        if (this.m_iPrivacyProtocol == iPrivacyProtocol) {
            return;
        }
        this.m_iPrivacyProtocol = iPrivacyProtocol;
    }

    protected void setUserName(final String strUserName) {
        if (strUserName == null) {
            return;
        }
        if (strUserName.equals(this.m_strUserName)) {
            return;
        }
        this.m_strUserName = strUserName;
    }

    protected void setContextEngineId(final String strContextEngineId) {
        if (strContextEngineId == null) {
            return;
        }
        if (strContextEngineId.equals(this.m_strContextEngineId)) {
            return;
        }
        this.m_strContextEngineId = strContextEngineId;
    }

    protected void setContextName(final String strContextName) {
        if (strContextName == null) {
            return;
        }
        if (this.m_strContextName.equals(strContextName)) {
            return;
        }
        this.m_strContextName = strContextName;
    }

    protected void setUseAuthentication(final boolean bUseAuthentication) {
        if (this.m_bUseAuthentication == bUseAuthentication) {
            return;
        }
        this.m_bUseAuthentication = bUseAuthentication;
    }

    protected void setUserAuthenticationPassword(final String strUserAuthenticationPassword) {
        if (strUserAuthenticationPassword == null) {
            return;
        }
        this.m_strUserAuthenticationPassword = strUserAuthenticationPassword;
    }

    protected void setUsePrivacy(final boolean bUsePrivacy) {
        if (this.m_bUsePrivacy == bUsePrivacy) {
            return;
        }
        this.m_bUsePrivacy = bUsePrivacy;
    }

    protected void setUserPrivacyPassword(final String strUserPrivacyPassword) {
        if (strUserPrivacyPassword == null) {
            return;
        }
        if (this.m_strUserPrivacyPassword.equals(strUserPrivacyPassword)) {
            return;
        }
        this.m_strUserPrivacyPassword = strUserPrivacyPassword;
    }

    public void setV3Params(final String strContextName, final String strContextEngineId, final String strUserName) {
        this.setV3Params(strContextName, strContextEngineId, strUserName, false, 0, "");
    }

    public void setV3Params(final String strContextName, final String strContextEngineId, final String strUserName, final boolean bUseAuthentication, final int iAuthenticationProtocol, final String strUserAuthenticationPassword) {
        this.setV3Params(strContextName, strContextEngineId, strUserName, bUseAuthentication, iAuthenticationProtocol, strUserAuthenticationPassword, false, SnmpTarget.DES_PROTOCOL, "");
    }

    public void setV3Params(final String strContextName, final String strContextEngineId, final String strUserName, final boolean bUseAuthentication, final int iAuthenticationProtocol, final String strUserAuthenticationPassword, final boolean bUsePrivacy, final int iPrivacyProtocol, final String strUserPrivacyPassword) {
        this.setContextName(strContextName);
        this.setContextEngineId(strContextEngineId);
        this.setUserName(strUserName);
        this.setUseAuthentication(bUseAuthentication);
        this.setAuthenticationProtocol(iAuthenticationProtocol);
        this.setUserAuthenticationPassword(strUserAuthenticationPassword);
        this.setUsePrivacy(bUsePrivacy);
        this.setPrivacyProtocol(iPrivacyProtocol);
        this.setUserPrivacyPassword(strUserPrivacyPassword);
        this.setUsm();
    }

    protected void setUsm() {
        if (this.context instanceof SnmpContextv3) {
            this.setUsm((SnmpContextv3Face) this.context);
        }
    }

    public void setUsm(final SnmpContextv3Face c) {
        try {
            if (!this.m_strContextName.equals("")) {
                c.setContextName(this.m_strContextName);
            }
            if (this.m_strContextEngineId == null || this.m_strContextEngineId.equals("")) {
                final TimeWindow tWindow = TimeWindow.getCurrent();
                this.m_strContextEngineId = tWindow.getSnmpEngineId(c.getHost(), c.getPort());
                log.debug(("--------> SnmpEngineId is [" + this.m_strContextEngineId + "]."));
            }
            final byte[] bytes = SnmpUtilities.toBytes(this.m_strContextEngineId);
            c.setContextEngineId(bytes);
            c.setUserName(this.m_strUserName);
            if (this.m_bUseAuthentication) {
                c.setUseAuthentication(true);
                c.setAuthenticationProtocol(this.m_iAuthenticationProtocol);
                c.setUserAuthenticationPassword(this.m_strUserAuthenticationPassword);
            } else {
                c.setUseAuthentication(false);
            }
            if (this.m_bUsePrivacy) {
                c.setUsePrivacy(true);
                c.setPrivacyProtocol(this.m_iPrivacyProtocol);
                c.setUserPrivacyPassword(this.m_strUserPrivacyPassword);
            } else {
                c.setUsePrivacy(false);
            }
            final UsmDiscoveryBean discBean = new UsmDiscoveryBean(c.getHost(), c.getPort(), c.getBindAddress(), c.getTypeSocket());
            discBean.setAuthenticationDetails(c.getUserName(), c.getUserAuthenticationPassword(), c.getAuthenticationProtocol());
            discBean.setPrivacyDetails(c.getUserPrivacyPassword(), c.getPrivacyProtocol());
            discBean.startDiscovery();
        } catch (Exception exc) {
           log.debug("" + exc);
        }
    }

    protected synchronized Varbind[] performRequest(final String type, final String[] oids, final AsnObject[] values, final SnmpResult r) {
        Pdu pdu = null;
        try {
            this.initContext();
            boolean isSetRequest = false;
            final int sz = oids.length;
            log.debug("<<-- mutual request start ---------------------------------------------------->>");
            log.debug(("Request host    is [" + this.context.getHost() + "]."));
            log.debug(("Request version is [" + this.context.getVersion() + "]."));
            log.debug(("Request port    is [" + this.context.getPort() + "]."));
            log.debug(("Request timeout is [" + this.m_timeout + "]."));
            log.debug(("Request retry   is [" + this.m_retries + "]."));
            log.debug(("Request type    is [" + type + "]."));
            if (type.equalsIgnoreCase("GET")) {
                pdu = new GetPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    pdu.addOid(oids[i]);
                }
            } else if (type.equalsIgnoreCase("GETNEXT")) {
                pdu = new GetNextPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    pdu.addOid(oids[i]);
                }
            } else if (type.equalsIgnoreCase("GETBULK")) {
                final OneGetBulkPdu p = new OneGetBulkPdu(this.context);
                p.setNonRepeaters(this.m_NonRepeaters);
                p.setMaxRepetitions(this.m_MaxRepetitions);
                pdu = p;
                for (int j = 0; j < sz; ++j) {
                    pdu.addOid(oids[j]);
                }
            } else if (type.equalsIgnoreCase("SET")) {
                isSetRequest = true;
                pdu = new SetPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    final Varbind var = new Varbind(oids[i], values[i]);
                    pdu.addOid(var);
                }
            } else if (type.equalsIgnoreCase("INFORM")) {
                pdu = new InformPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    final Varbind var = new Varbind(oids[i], values[i]);
                    pdu.addOid(var);
                }
            } else {
                log.debug("error mutual version...");
            }
            if (pdu.getErrorStatus() != 0) {
                log.debug(pdu.getErrorStatusString());
                return null;
            }
            if (this.m_retries != -1) {
                final int retries = this.m_retries + 1;
                final int[] retryIntervals = new int[retries];
                for (int k = 0; k < retries; ++k) {
                    retryIntervals[k] = this.m_timeout * 1000;
                }
                pdu.setRetryIntervals(retryIntervals);
            }
            if (isSetRequest && this.m_writeCommunity != null) {
                if (this.context instanceof SnmpContext) {
                    ((SnmpContext) this.context).setCommunity(this.m_writeCommunity);
                    log.debug(("Request Community is [" + this.m_writeCommunity + "]."));
                } else if (this.context instanceof SnmpContextv2c) {
                    ((SnmpContextv2c) this.context).setCommunity(this.m_writeCommunity);
                    log.debug(("Request Community is [" + this.m_writeCommunity + "]."));
                }
            } else if (this.context instanceof SnmpContext) {
                ((SnmpContext) this.context).setCommunity(this.m_community);
                log.debug(("Request Community is [" + this.m_community + "]."));
            } else if (this.context instanceof SnmpContextv2c) {
                ((SnmpContextv2c) this.context).setCommunity(this.m_community);
                log.debug(("Request Community is [" + this.m_community + "]."));
            }
            for (int i = 0; i < oids.length; ++i) {
                if (values == null) {
                    log.debug(("Request OID [" + oids[i] + "]."));
                } else {
                    log.debug(("Request OID [" + oids[i] + "] value [" + values[i] + "]."));
                }
            }
            pdu.send();
            pdu.waitForSelf();
            log.debug(("Request   id [" + pdu.getReqId() + "]."));
            log.debug(("ErrCode   is [" + pdu.getErrorStatus() + "]."));
            log.debug(("ErrDesc   is [" + pdu.getErrorStatusString() + "]."));
            log.debug(("ErrIndex  is [" + pdu.getErrorIndex() + "]."));
            log.debug(("isTimeout is [" + pdu.isTimedOut() + "]."));
            r.err_code = pdu.getErrorStatus();
            r.err_desc = pdu.getErrorStatusString();
            this.m_errCode = r.err_code;
            this.m_errDesc = r.err_desc;
            if (pdu.getErrorStatus() == 5 && pdu.isTimedOut()) {
                log.debug(("Snmp Request [" + pdu.getReqId() + "] is Timeout, set ErrCode to [22]."));
                this.m_errCode = 22;
                this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            }
            Varbind[] binds = null;
            if (pdu.getErrorStatus() == 0) {
                binds = pdu.getResponseVarbinds();
            }
            if (r.err_code == 0) {
                for (int j = 0; j < binds.length; ++j) {
                    log.debug(("result Varbinds OID [" + binds[j].getOid().toString() + "] value [" + binds[j].getValue().toString() + "]"));
                }
            }
            log.debug("<<-- mutual request end ---------------------------------------------------->>");
            return binds;
        } catch (NullPointerException e2) {
            this.m_errCode = 10000;
            this.m_errDesc = "Cannot create SnmpContext instance.";
        } catch (Exception e) {
            this.m_errCode = 23;
            this.m_errDesc = pdu.getErrorStatusString();
            log.debug("" + e);
        } finally {
            this.releaseSnmpSession();
        }
        return null;
    }

    protected synchronized Varbind[] performRequestWithReturnBinds(final String type, final String[] oids, final AsnObject[] values, final SnmpResult r) {
        Pdu pdu = null;
        try {
            this.initContext();
            boolean isSetRequest = false;
            final int sz = oids.length;
            log.debug("<<-- mutual request start ---------------------------------------------------->>");
            log.debug(("Request host    is [" + this.context.getHost() + "]."));
            log.debug(("Request version is [" + this.context.getVersion() + "]."));
            log.debug(("Request port    is [" + this.context.getPort() + "]."));
            log.debug(("Request timeout is [" + this.m_timeout + "]."));
            log.debug(("Request retry   is [" + this.m_retries + "]."));
            log.debug(("Request type    is [" + type + "]."));
            if (type.equalsIgnoreCase("GET")) {
                pdu = new GetPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    pdu.addOid(oids[i]);
                }
            } else if (type.equalsIgnoreCase("GETNEXT")) {
                pdu = new GetNextPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    pdu.addOid(oids[i]);
                }
            } else if (type.equalsIgnoreCase("GETBULK")) {
                final OneGetBulkPdu p = new OneGetBulkPdu(this.context);
                p.setNonRepeaters(this.m_NonRepeaters);
                p.setMaxRepetitions(this.m_MaxRepetitions);
                pdu = p;
                for (int j = 0; j < sz; ++j) {
                    pdu.addOid(oids[j]);
                }
            } else if (type.equalsIgnoreCase("SET")) {
                isSetRequest = true;
                pdu = new SetPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    final Varbind var = new Varbind(oids[i], values[i]);
                    pdu.addOid(var);
                }
            } else if (type.equalsIgnoreCase("INFORM")) {
                pdu = new InformPdu_vec(this.context, sz);
                for (int i = 0; i < sz; ++i) {
                    final Varbind var = new Varbind(oids[i], values[i]);
                    pdu.addOid(var);
                }
            } else {
                log.debug("error mutual version...");
            }
            if (pdu.getErrorStatus() != 0) {
                log.debug(pdu.getErrorStatusString());
                return null;
            }
            if (this.m_retries != -1) {
                final int retries = this.m_retries + 1;
                final int[] retryIntervals = new int[retries];
                for (int k = 0; k < retries; ++k) {
                    retryIntervals[k] = this.m_timeout * 1000;
                }
                pdu.setRetryIntervals(retryIntervals);
            }
            if (isSetRequest && this.m_writeCommunity != null) {
                if (this.context instanceof SnmpContext) {
                    ((SnmpContext) this.context).setCommunity(this.m_writeCommunity);
                    log.debug(("Request Community is [" + this.m_writeCommunity + "]."));
                } else if (this.context instanceof SnmpContextv2c) {
                    ((SnmpContextv2c) this.context).setCommunity(this.m_writeCommunity);
                    log.debug(("Request Community is [" + this.m_writeCommunity + "]."));
                }
            } else if (this.context instanceof SnmpContext) {
                ((SnmpContext) this.context).setCommunity(this.m_community);
                log.debug(("Request Community is [" + this.m_community + "]."));
            } else if (this.context instanceof SnmpContextv2c) {
                ((SnmpContextv2c) this.context).setCommunity(this.m_community);
                log.debug(("Request Community is [" + this.m_community + "]."));
            }
            for (int i = 0; i < oids.length; ++i) {
                if (values == null) {
                    log.debug(("Request OID [" + oids[i] + "]."));
                } else {
                    log.debug(("Request OID [" + oids[i] + "] value [" + values[i] + "]."));
                }
            }
            pdu.send();
            pdu.waitForSelf();
            log.debug(("Request   id [" + pdu.getReqId() + "]."));
            log.debug(("ErrCode   is [" + pdu.getErrorStatus() + "]."));
            log.debug(("ErrDesc   is [" + pdu.getErrorStatusString() + "]."));
            log.debug(("ErrIndex  is [" + pdu.getErrorIndex() + "]."));
            log.debug(("isTimeout is [" + pdu.isTimedOut() + "]."));
            r.err_code = pdu.getErrorStatus();
            r.err_desc = pdu.getErrorStatusString();
            this.m_errCode = r.err_code;
            this.m_errDesc = r.err_desc;
            if (pdu.getErrorStatus() == 5 && pdu.isTimedOut()) {
                log.debug(("Snmp Request [" + pdu.getReqId() + "] is Timeout, set ErrCode to [22]."));
                this.m_errCode = 22;
                this.m_errDesc = ErrorMessages.getErrorString(this.m_errCode);
            }
            final Varbind[] binds = pdu.getResponseVarbinds();
            if (r.err_code == 0) {
                for (int j = 0; j < binds.length; ++j) {
                    log.debug(("result Varbinds OID [" + binds[j].getOid().toString() + "] value [" + binds[j].getValue().toString() + "]"));
                }
            }
            log.debug("<<-- mutual request end ---------------------------------------------------->>");
            return binds;
        } catch (NullPointerException e2) {
            this.m_errCode = 10000;
            this.m_errDesc = "Cannot create SnmpContext instance.";
        } catch (Exception e) {
            this.m_errCode = 23;
            this.m_errDesc = pdu.getErrorStatusString();
            log.debug("" + e);
        } finally {
            this.releaseSnmpSession();
        }
        return null;
    }

    protected static SnmpContextBasisFace newSnmpContext(final int version, final String hostname, final int port) {
        SnmpContextBasisFace context = null;
        try {
            if (0 == version) {
                final SnmpContext c = new SnmpContext(hostname, port);
                c.setMaxRecvSize(SnmpTarget.maxRecvSize);
                context = c;
            } else if (1 == version) {
                final SnmpContextv2c c2 = new SnmpContextv2c(hostname, port);
                c2.setMaxRecvSize(SnmpTarget.maxRecvSize);
                context = c2;
            } else if (3 == version) {
                final SnmpContextv3 c3 = new SnmpContextv3(hostname, port);
                c3.setMaxRecvSize(SnmpTarget.maxRecvSize);
                context = c3;
            } else {
                log.debug(("------> Unsport Snmp Version [" + version + "]."));
            }
        } catch (Exception e) {
            log.debug("" + e);
        }
        return context;
    }

    static {
        SnmpTarget.isSessionCtrl = false;
        SnmpTarget.maxRecvSize = 1472;
        SnmpTarget.SHA1_PROTOCOL = 1;
        SnmpTarget.MD5_PROTOCOL = 0;
        SnmpTarget.AES_PROTOCOL = 3;
        SnmpTarget.DES_PROTOCOL = 2;
        try {
            DefaultTrapContext.getInstance(0);
        } catch (Exception e) {
            log.debug("" + e);
        }
    }

    class SnmpResult {
        public int err_code;
        public String err_desc;

        SnmpResult() {
            this.err_code = 0;
            this.err_desc = "";
        }
    }
}
